#!/usr/bin/env bash

set -e

source @CMAKE_BINARY_DIR@/config.sh -p

# Define Parameters ###########################################################
INPUT_EVENTS="100"
INPUT_EVENTS_OPT="--nof-events $INPUT_EVENTS"
CHUNK_SIZE="--chunk-size 10"
DATA_FILE="@splitmc_file_location@/MQ.simulation_@pixel_simulation_engine@.data.root"
DATA_FILE_OPT="--file-name $DATA_FILE"
PARS_FILE="--output-name @splitmc_file_location@/MQ.simulation_@pixel_simulation_engine@.pars.root"
DETECTOR_LIB="--detector-library @CMAKE_BINARY_DIR@/lib/libExPixel.@example_library_extension@"
RUNNING_MODE="--running-mode pp"
TRANSPORT_NAME="--transport-name @pixel_simulation_engine@"
COMMON_OPTS="--transport zeromq --severity debug --control static --color false"

# Declare Channels ############################################################
declare -A CH_ADDR
declare -A CH_NAME
declare -A CHANNEL

CH_NAME[PRIMARIES]="primariesChannel"
CH_ADDR[PRIMARIES]="ipc://${CH_NAME[PRIMARIES]}"
CHANNEL[PRIMARIES]="--channel-config name=${CH_NAME[PRIMARIES]},address=${CH_ADDR[PRIMARIES]},rateLogging=1"

CH_NAME[DATA]="data#all#"
CH_ADDR[DATA]="ipc://dataAll"
CHANNEL[DATA]="--channel-config name=${CH_NAME[DATA]},address=${CH_ADDR[DATA]},rateLogging=1"

CH_NAME[DATAOUT]="dataOut"
CH_ADDR[DATAOUT]="ipc://${CH_NAME[DATAOUT]}"
CHANNEL[DATAOUT]="--channel-config name=${CH_NAME[DATAOUT]},address=${CH_ADDR[DATAOUT]},rateLogging=1"

CH_NAME[UPDATE]="updateChannel"
CH_ADDR[UPDATE]="ipc://${CH_NAME[UPDATE]}"
CHANNEL[UPDATE]="--channel-config name=${CH_NAME[UPDATE]},address=${CH_ADDR[UPDATE]},rateLogging=1"

CH_NAME[ACK]="ack"
CH_ADDR[ACK]="ipc://${CH_NAME[ACK]}"
CHANNEL[ACK]="--channel-config name=${CH_NAME[ACK]},address=${CH_ADDR[ACK]},rateLogging=1"

# Declare Devices ############################################################
declare -A DEVICES

set -x
DEVICES[GENERATOR]="@splitmc_bin_location@/pixel-sim-gen --id generator \
  --ack-channel ${CH_NAME[ACK]} ${CHANNEL[ACK]},type=pull,method=bind \
  ${CHANNEL[PRIMARIES]},type=push,method=bind \
  $CHUNK_SIZE $INPUT_EVENTS_OPT $RUNNING_MODE $COMMON_OPTS"

DEVICES[TRANSPORTER]="@splitmc_bin_location@/pixel-sim-transport --id transporter \
  ${CHANNEL[DATA]},type=push,method=connect \
  ${CHANNEL[PRIMARIES]},type=pull,method=connect \
  ${CHANNEL[UPDATE]},type=req,method=connect \
  $DETECTOR_LIB $RUNNING_MODE $TRANSPORT_NAME $COMMON_OPTS"

DEVICES[MERGER]="@splitmc_bin_location@/pixel-sim-chunk-merger --id merger \
  --in-channel ${CH_NAME[DATA]} ${CHANNEL[DATA]},type=pull,method=bind \
  --out-channel ${CH_NAME[DATAOUT]} ${CHANNEL[DATAOUT]},type=push,method=bind \
  $COMMON_OPTS"

DEVICES[FILESINK]="@pixel_bin_dir@/pixel-sink --id filesink \
  --ack-channel ${CH_NAME[ACK]} ${CHANNEL[ACK]},type=push,method=connect \
  --in-channel ${CH_NAME[DATAOUT]} ${CHANNEL[DATAOUT]},type=pull,method=connect \
  $DATA_FILE_OPT $COMMON_OPTS"

DEVICES[PARMQSERVER]="@fairroot_bin_dir@/parmq-server --id parmq-server \
  --update-channel-name ${CH_NAME[UPDATE]} ${CHANNEL[UPDATE]},type=rep,method=bind \
  $PARS_FILE $COMMON_OPTS"
set +x

# Run Controller ##############################################################
echo "Starting topology ..."

rm -rf $DATA_FILE # Make sure there is no data file from previous run

declare -A PIDS
declare -A LOGS
for DEVICE in "${!DEVICES[@]}"
do
  LOGS[$DEVICE]="$(pwd)/$DEVICE.log"
  printf "%12s: " $DEVICE
  ${DEVICES[$DEVICE]} > ${LOGS[$DEVICE]} 2>&1 &  # Run device
  PIDS[$DEVICE]=$!
  echo "PID=${PIDS[$DEVICE]}, LOG=${LOGS[$DEVICE]}"
done

echo "... topology running."

RC=0
echo "Waiting for GENERATOR(${PIDS[GENERATOR]}) to finish ... "
wait ${PIDS[GENERATOR]} || { ret=$?; echo "GENERATOR failed with exit code $ret"; RC=$(($RC + $ret)); }
sleep 1
echo "... finished (RC=$RC)."

echo "Terminating topology ..."
kill ${PIDS[TRANSPORTER]} ${PIDS[MERGER]} ${PIDS[PARMQSERVER]} ${PIDS[FILESINK]}
for DEVICE in TRANSPORTER MERGER PARMQSERVER FILESINK
do
  wait ${PIDS[$DEVICE]} || {
    ret=$?
    echo "*** $DEVICE failed with exit code $ret"
    RC=$(($RC + $ret))
    echo "    Last lines of log:"
    tail -n 50 "${LOGS[$DEVICE]}" | sed -e 's/^/    | /'
  }
done
echo "... terminated (RC=$RC)."

if [[ "$RC" -ne "0" ]]; then
  exit $RC
fi

# Test Results ################################################################
echo "Checking results ..."
OUTPUT_EVENTS="$(echo "cout<<cbmsim->GetEntries()<<endl;" | @ROOT_EXECUTABLE@ -l -b $DATA_FILE | tail -1)"
if [[ "$OUTPUT_EVENTS" -eq "$INPUT_EVENTS" ]]
then
  echo " ==> There are $OUTPUT_EVENTS/$INPUT_EVENTS events in the data file. :-)"
else
  echo " ==> Found only $OUTPUT_EVENTS/$INPUT_EVENTS in data file. :-("
  exit 1
fi
